package up6.biz;

import com.google.gson.Gson;
import org.apache.commons.lang.StringUtils;
import up6.PathTool;
import up6.database.DBConfig;
import up6.database.DBFile;
import up6.database.DbFolder;
import up6.database.DbHelper;
import up6.model.FileInf;

import java.io.*;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用法
 * FolderSchemaDB db = new FolderSchemaDB();
 * db.save(FileInf);
 * @author qwl
 * 更新：
 *  2020-11-30 完善相对路径更新逻辑。
 *
 */
public class FolderSchemaDB {
	
	FileInf m_root;
	List<FileInf> m_files;
	List<FileInf> m_folders;
	Map<String,FileInf> m_dirs;//pathSvr,fd
	
	//保存所有文件的父级目录信息
	public void parseParent() 
	{
		for(int i=0 , l = m_files.size() ; i < l ; ++i)
		{
			FileInf file = (FileInf)m_files.get(i);
			FileInf dir = new FileInf();
			dir.id = file.pid;
			dir.uid = this.m_root.uid;
			dir.pidRoot = file.pidRoot;
			dir.pathSvr = file.parentDir();
			dir.pathRel = dir.pathSvr.replaceAll(this.m_root.pathSvr, "");
			dir.nameLoc = PathTool.getName(dir.pathSvr);
			dir.nameSvr = dir.nameLoc;
			dir.fdChild = true;
			dir.complete = true;			
			
			//添加不存在的目录
			if(!this.m_dirs.containsKey(dir.pathSvr))
			{
				this.m_folders.add(dir);
				this.m_dirs.put(dir.pathSvr, dir);
			}
		}
	}
	
	//递归分析和保存父级目录
	public void parseDirs() 
	{
		for(int i=0 , l = m_folders.size() ; i < l ; ++i)
		{
			FileInf file = m_folders.get(i);
			
			String dir = file.pathSvr;
			int pos = dir.indexOf("/", this.m_root.pathSvr.length());
			while( -1 != pos)
			{
				FileInf fd = new FileInf();
				fd.uid = this.m_root.uid;
				fd.pathSvr = dir.substring(0, pos);
				fd.pidRoot = this.m_root.id;
				fd.pathRel = fd.pathSvr.replace(this.m_root.pathSvr, "");
				fd.nameLoc = PathTool.getName(fd.pathSvr);
				fd.nameSvr = fd.nameLoc;
				fd.complete = true;
				fd.fdChild = true;
				
				//不存在
				if(!this.m_dirs.containsKey(fd.pathSvr))
				{
					fd.id = PathTool.guid();
					this.m_folders.add(fd);//添加目录
					this.m_dirs.put(fd.pathSvr, fd);//添加字典
				}
				
				pos = dir.indexOf("/", pos+1);
			}
		}
	}
	
	//更新所有目录的PID
	public void updatePID() 
	{
		//更新目录pid
		for(int i=1 , l = m_folders.size() ; i < l ; ++i)
		{
			FileInf fd = (FileInf)m_folders.get(i);
			if( StringUtils.isEmpty(fd.pid) )
			{
				String dir = fd.parentDir();
				FileInf pfd = (FileInf)this.m_dirs.get(dir);
				fd.pid = pfd.id;
			}
		}
		
		//更新文件pid
		for(int i = 0,l=this.m_files.size();i<l;++i)
		{
			FileInf f = this.m_files.get(i);
			String dir = f.parentDir();
			FileInf fd = this.m_dirs.get(dir);
			f.pid = fd.id;
		}
	}

    /// <summary>
    /// 更新文件和目录相对路径
    ///     1.增加根目录前缀
    /// </summary>
    void updatePathRel()
    {
    	for(FileInf fd : this.m_folders)
    	{
            if (!StringUtils.isEmpty(fd.pid) )
                //更新相对路径->增加根目录前缀
                fd.pathRel = PathTool.combin(this.m_root.pathRel , fd.pathRel);    		
    	}

    	for(FileInf f : this.m_files)
    	{
    		f.pathRel = PathTool.combin( this.m_root.pathRel , f.pathRel);
    	}
    }

    private void loadFiles(FileInf dir) throws IOException
	{
		//加载folder.txt
		File f = new File(dir.schemaFile());
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f),"UTF-8"));
		String line = null;
		Gson g = new Gson();
		Map<String,Boolean> dic = new HashMap<String,Boolean>();

		while( (line = br.readLine() )!=null )
		{
			FileInf item = g.fromJson(line, FileInf.class);
			item.uid = this.m_root.uid;

			//防止重复添加
			if(!dic.containsKey(item.id))
			{
				if(item.fdTask)
				{
					this.m_folders.add(item);
					this.m_dirs.put(item.pathSvr, item);
				}
				else
				{
					this.m_files.add(item);
				}
				dic.put(item.id,true);
			}
		}
		br.close();
	}

	//保存到数据库
	public void save(FileInf dir) throws IOException, SQLException
	{
		this.m_root = dir;
		this.m_files = new ArrayList<FileInf>();
		this.m_folders = new ArrayList<FileInf>();
		this.m_dirs = new HashMap<String,FileInf>(); 

		//加载层级结构
		this.loadFiles(dir);
		
		//分析
		this.parseParent();
		this.parseDirs();
		this.updatePID();
		this.updatePathRel();
		
		//写入数据库
		DBConfig cfg = new DBConfig();
		DbFolder db = cfg.folder();
		//取消根目录
		this.m_folders.remove(0);
		db.addBatch(this.m_folders);
		
		DBFile dbf = cfg.db();
		dbf.addBatch(this.m_files);
	}	

	
	/// <summary>
    /// 覆盖文件
    /// </summary>
    /// <param name="files"></param>
	protected void cover_files()
	{
		String sql = "update up6_files set f_deleted=1 where f_pathRel=?";
		
		DbHelper db = new DbHelper();
		PreparedStatement cmd = db.GetCommand(sql);
		try {
			cmd.setString(1, "");
			for(FileInf f : this.m_files)
	    	{
				cmd.setString(1, f.pathRel);//id
		        cmd.executeUpdate();
	    	}
			cmd.getConnection().close();
			cmd.close();
		} catch (SQLException e) {e.printStackTrace();}
	}
	
	/// <summary>
    /// 覆盖文件夹
    /// </summary>
    /// <param name="files"></param>
	protected void cover_folders()
	{
		String sql = "update up6_folders set f_deleted=1 where f_pathRel=?";
		
		DbHelper db = new DbHelper();
		PreparedStatement cmd = db.GetCommand(sql);
		try {
			cmd.setString(1, "");
			for(FileInf f : this.m_folders)
	    	{
				cmd.setString(1, f.pathRel);//id
		        cmd.executeUpdate();
	    	}
			cmd.getConnection().close();
			cmd.close();
		} catch (SQLException e) {e.printStackTrace();}
	}
	
	public void cover()
    {
        this.cover_files();
        this.cover_folders();
    }
}
